package predictors.queuetimepredictor;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import java.sql.Connection;
import java.util.Iterator;

import objects.predictors.AttrInfo;
import objects.shared.WorkPacket;
import objects.user.UserInfo;



import utils.Utils;


import database.ConnectionManager;

public class AttributeMatcherImpl{

	
	public static AttrInfo GetAttributeInfo(int clusterId, int reqnodes,
			int reqprocs, int walltime) throws Exception {

		Connection conn = ConnectionManager.ds.getConnection();
		String query = "select freenodes,runjobs,qjobs from clu_data where id= ? order by id desc limit 1";
		PreparedStatement stmt = conn.prepareStatement(query);
		stmt.setInt(1, clusterId);
		ResultSet rs = stmt.executeQuery();
		rs.first();
		int freenodes = rs.getInt("freenodes");
		//int freeprocs = rs.getInt("freeprocs");
		int runjobs = rs.getInt("runjobs");
		int qjobs = rs.getInt("qjobs");
		query = "select * from myjobs where id= ? and qtime > 0 order by ABS(reqnodes - ?),ABS(reqprocs - ?),ABS(walltime - ?),ABS(freenodes - ?),ABS(runjobs - ?),ABS(qjobs - ?) limit 20";
		stmt = conn.prepareStatement(query);
		stmt.setInt(1, clusterId);
		stmt.setInt(2, reqnodes);
		stmt.setInt(3, reqprocs);
		stmt.setInt(5, walltime);
		stmt.setInt(4, freenodes);
		stmt.setInt(6, runjobs);
		stmt.setInt(7, qjobs);
		//System.out.println(stmt.toString());
		rs = stmt.executeQuery();
		double mean = 0;
		int tot = 0;
		int weight = 20;
		double std_dev = 0;
		int low = Integer.MAX_VALUE;
		int i = 0;
		while (rs.next()) {
			int val = rs.getInt("qtime");
			
			if (val < low)
				low = val;
			tot += (val * weight);
			Utils.out("+ [Instance] "+(i++)+" qt:"+val +" n:"+rs.getInt("reqnodes")+" ppn:"+rs.getInt("reqprocs")+" wt:"+rs.getInt("walltime")+" fn:"+rs.getInt("freenodes"));
			weight--;
		}
		mean = (double) tot / 210;
		mean = (mean + low) / 2;
		
		Utils.out("\nSystem: "+clusterId);
		Utils.out("Predicted queue time (mean val): "+Utils.f.format(mean)+" seconds");
		Utils.out(" -------------------------------------");
		rs.beforeFirst();
		while (rs.next()) {
			double val = rs.getInt("qtime") - mean;
			std_dev += val * val;
		}
		std_dev /= 10;
		std_dev = Math.sqrt(std_dev);
		conn.close();
		return new AttrInfo(low, mean, std_dev, clusterId);
	}
	
	public static AttrInfo GetLowestQtime(WorkPacket wp,UserInfo ui) throws Exception
	{
		Utils.out(" ------ Queue time predictor HC ------");
		Iterator<Integer> it = ui.clusterMap.keySet().iterator();
		AttrInfo best = new AttrInfo();
		while(it.hasNext())
		{
			int clusterId = it.next();
			Utils.out(clusterId);
			AttrInfo i = GetAttributeInfo(clusterId,wp.nodes,wp.ppn,Utils.ConvertWalltime(wp.walltime));
			if(i.mean < best.mean)
			{
				
				best.low_bound = i.low_bound;
				best.mean = i.mean;
				best.std_dev = i.std_dev;
				best.cluster = clusterId;
			}
		}
		best.jobId = wp.uniqueId;
		Utils.out(" ===========================");
		Utils.out("+ Found lowest queue time : "+ Utils.f.format(best.mean)+" seconds, on system '"+best.cluster);
		Utils.out(" ===========================\n\n");
		return best;
	}
}
